﻿
using Microsoft.Extensions.DependencyInjection.Extensions;
using Microsoft.Extensions.DependencyInjection;
using Volo.Abp.Domain;
using Volo.Abp.Domain.Repositories;
using Volo.Abp.Modularity;
using Kstopa.Sqlsugar.Abstractions;
using Kstopa.Sqlsugar.Repositories;
using Kstopa.Sqlsugar.Uow;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using SqlSugar;
using System.Reflection;
using System.Text;
using Volo.Abp.Data;
using Volo.Abp;
using Kstopa.Domain;
using Yitter.IdGenerator;
using Kstopa.Cache;
using Microsoft.EntityFrameworkCore;

namespace Kstopa.Sqlsugar
{
    [DependsOn(typeof(KstopaDomainModule),
        typeof(KstopaAbpCacheModule))]

    public class AbpSqlSugarCoreModule : AbpModule
    {
        public override Task ConfigureServicesAsync(ServiceConfigurationContext context)
        {
            //...
            var service = context.Services;
            var configuration = service.GetConfiguration();
            Configure<DbConnOptions>(configuration.GetSection("DbConnOptions"));
            //雪花ID注入
            YitIdHelper.SetIdGenerator(new IdGeneratorOptions
            {
                WorkerId = 1// 取值范围0~63,默认1
            });
            service.TryAddScoped<ISqlSugarDbContext, SqlSugarDbContext>();

            //不开放sqlsugarClient
            //service.AddTransient<ISqlSugarClient>(x => x.GetRequiredService<ISqlsugarDbContext>().SqlSugarClient);


            service.AddTransient(typeof(IRepository<>), typeof(SqlSugarRepository<>));
            service.AddTransient(typeof(IRepository<,>), typeof(SqlSugarRepository<,>));
            service.AddTransient(typeof(ISqlSugarRepository<>), typeof(SqlSugarRepository<>));
            service.AddTransient(typeof(ISqlSugarRepository<,>), typeof(SqlSugarRepository<,>));

            service.AddTransient(typeof(ISugarDbContextProvider<>), typeof(UnitOfWorkSqlsugarDbContextProvider<>));

            return Task.CompletedTask;
        }




        public override async Task OnPreApplicationInitializationAsync(ApplicationInitializationContext context)
        {
            //进行CodeFirst
            var service = context.ServiceProvider;
            var options = service.GetRequiredService<IOptions<DbConnOptions>>().Value;
            var _logger = service.GetRequiredService<ILogger<AbpSqlSugarCoreModule>>();
            var fullName = Assembly.GetExecutingAssembly().FullName;//获取程序集全名

            StringBuilder sb = new StringBuilder();
            sb.AppendLine();
            sb.AppendLine("==========Yi-SQL配置:==========");
            sb.AppendLine($"数据库连接字符串：{options.Url}");
            sb.AppendLine($"数据库类型：{options.DbType.ToString()}");
            sb.AppendLine($"是否开启种子数据：{options.EnabledDbSeed}");
            sb.AppendLine($"是否开启CodeFirst：{options.EnabledCodeFirst}");
            sb.AppendLine($"是否开启Saas多租户：{options.EnabledSaasMultiTenancy}");
            sb.AppendLine("===============================");


            _logger.LogInformation(sb.ToString());
            //Todo：准备支持多租户种子数据及CodeFirst

            if (options.EnabledCodeFirst)
            {
                CodeFirst(service, fullName);
            }
            if (options.EnabledDbSeed)
            {
                await DataSeedAsync(service);
            }
        }

        private void CodeFirst(IServiceProvider service, string assemblyName)
        {

            var moduleContainer = service.GetRequiredService<IModuleContainer>();
            var db = service.GetRequiredService<ISqlSugarDbContext>().SqlSugarClient;

            //尝试创建数据库
            db.DbMaintenance.CreateDatabase();

            List<Type> entityTypes = new List<Type>();

            // 获取所有实体表-初始化表结构
            foreach (var module in moduleContainer.Modules)
            {
                entityTypes.AddRange(module.Assembly.GetTypes().
                    Where(u => !u.IsInterface && !u.IsAbstract && u.IsClass && u.IsDefined(typeof(SugarTable), false)));
            }
         
            if (!entityTypes.Any()) return;//没有就退出
            foreach (var entityType in entityTypes)
            {
                var tenantAtt = entityType.GetCustomAttribute<TenantAttribute>();//获取Sqlsugar多租户特性
                var ignoreInit = entityType.GetCustomAttribute<IgnoreInitTableAttribute>();//获取忽略初始化特性
                if (ignoreInit != null) continue;//如果有忽略初始化特性
                if (tenantAtt == null) continue;//如果没有租户特性就下一个
                //var db = db.GetConnectionScope(tenantAtt.configId.ToString());//获取数据库对象
                var splitTable = entityType.GetCustomAttribute<SplitTableAttribute>();//获取自动分表特性
                if (splitTable == null)//如果特性是空
                    db.CopyNew().CodeFirst.InitTables(entityType);//普通创建
                else
                    db.CopyNew().CodeFirst.SplitTables().InitTables(entityType);//自动分表创建
            }
        }

        private async Task DataSeedAsync(IServiceProvider service)
        {
            var dataSeeder = service.GetRequiredService<IDataSeeder>();
            await dataSeeder.SeedAsync();
        }
    }
}
